//      xfer.c
//      
//      Copyright 2011 DJ Shaji <djshaji@gmail.com>
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.


#include "xfer.h"

void xfer_update_copy_process ( goffset current, goffset total, Copy * copy )
{
	gtk_progress_bar_set_fraction ( copy -> bar1, ( gfloat ) current / ( gfloat ) total ) ;
	gtk_progress_bar_set_fraction ( copy -> bar2, ( gfloat ) copy -> current_file / ( gfloat ) copy -> total_files ) ;
	
	april_update_gui () ;
}

void xfer_populate_folder ( GList * list, gchar * folder )
{
	GError * error = null ;
	GDir * dir = g_dir_open ( folder, 0, & error ) ;
	
	if ( error )
	{
		g_warning ( "Cannot read folder: %s", error -> message ) ;
		return ;
	
	}
	
	gchar * name = g_dir_read_name ( dir ) ;
	while ( name )
	{
		gchar * full_name = g_build_filename ( folder, name, null ) ;
		list = g_list_append ( list, full_name ) ;
		
		if ( g_file_test ( full_name, G_FILE_TEST_IS_DIR ))
			xfer_populate_folder ( list, full_name ) ;
			
		name = g_dir_read_name ( dir ) ;
	}
	
	g_dir_close ( dir ) ;
}
		


void xfer_copy ( Explorer * e, gchar * source, gchar * destination )
{
	GtkDialog * dialog = gtk_dialog_new_with_buttons ( "Copying files ...",
							e -> window,
							GTK_DIALOG_MODAL,
							"Cancel",
							0,
							null ) ;
	
	GtkImage * image = gtk_image_new_from_stock ( "gtk-copy", GTK_ICON_SIZE_DIALOG ) ;
	gchar * markup = g_markup_printf_escaped ( 
						"<span size=\"large\"><b>"
						"Copying files ...\n\n"
						"</b></span>"
						"Please wait while files are being copied." ) ;
	
	GtkLabel * l = gtk_label_new ( null ) ;
	gtk_label_set_markup ( l, markup ) ;
	
	g_free ( markup ) ;
	
	GtkWidget * hbox = gtk_hbox_new ( no, 0 ) ;
	GtkWidget * vbox = gtk_hbox_new ( no, 0 ) ;
	
	gtk_box_pack_start ( hbox, image, no, no, 5 ) ;
	gtk_box_pack_start ( hbox, l, yes, yes, 2 ) ;
	
	gtk_box_pack_start ( vbox, hbox, yes, yes, 5 ) ;
	gtk_label_set_line_wrap ( l, on ) ;

	GtkProgressBar  * bar1 = gtk_progress_bar_new (),
					* bar2 = gtk_progress_bar_new () ;
	
	gtk_box_pack_start ( vbox, bar1, no, no, 2 ) ;
	gtk_box_pack_start ( vbox, bar2, no, no, 2 ) ;
	
	gtk_box_pack_start ( dialog -> vbox, vbox, yes, yes, 5 ) ;
	gtk_widget_show_all ( dialog ) ;
	
	GList * list = null ;
	if ( g_file_test ( source, G_FILE_TEST_IS_DIR ))
		xfer_populate_folder ( list, source ) ;
	else
		list = g_list_append ( list, g_strdup ( source )) ;
	
	gint i = 0, len = g_list_length ( list ) ;
	GCancellable * cancellable = g_cancellable_new () ;
	
	Copy copy ;
	
	copy.bar1 = bar1 ;
	copy.bar2 = bar2 ;
	
	copy.list = list ;
	copy.total_files = len ;
	
	copy.current_file = 0 ;
	copy.cancellable = cancellable ;
	
	gboolean source_file_is_regular = g_file_test ( source, G_FILE_TEST_IS_REGULAR ) ;
	
	for ( i = 0 ; i < len ; i ++ )
	{
		GFile * f1 = g_file_new_for_path ( g_list_nth_data ( list, i )),
			  * f2 = null ;
		
		copy.current_file = i ;
		
		if ( source_file_is_regular )
		{
			copy.current_file = 1 ;
			copy.total_files = 2 ;
			
			f2 = g_file_new_for_path ( destination ) ;
			GError * error = null ;
			
			if ( g_file_test ( destination, G_FILE_TEST_EXISTS ))
			{
				gchar * m = g_strdup_printf ( "The file %s exists. Overwrite ?", destination ) ;
				if ( prompt_question ( m ))
					g_file_copy ( f1, f2, G_FILE_COPY_OVERWRITE, cancellable,
									& copy, e, & error ) ;
				
				g_free ( m ) ;
			}
			
			else
				g_file_copy ( f1, f2, G_FILE_COPY_OVERWRITE, cancellable,
					& copy, e, & error ) ;

			if ( error )
				g_critical ( "Cannot copy file: %s", error -> message ) ;
				
			g_object_unref ( cancellable ) ;
			g_object_unref ( f1 ) ;
			
			g_object_unref ( f2 ) ;
			
			g_list_foreach ( list, g_free, null ) ;
			g_list_free ( list ) ;
			
			gtk_widget_destroy ( dialog ) ;
			return ;
		}

		gchar * new_name = g_build_filename ( source, g_list_nth_data ( list, i ), null ) ;
		
		/* We might not need this
		if ( g_file_test ( g_list_nth_data ( list, i ), G_FILE_TEST_IS_DIR ))
			g_mkdir_with_parents ( new_name, 0777 ) ;
		*/
		
		f2 = g_file_new_for_path ( new_name ) ;
		GError * error = null ;
		
		if ( g_file_test ( new_name, G_FILE_TEST_EXISTS ) && ! g_file_test ( new_name, G_FILE_TEST_IS_DIR ))
		{
			gchar * m = g_strdup_printf ( "The file %s exists. Overwrite ?", new_name ) ;
			if ( prompt_question ( m ))
				g_file_copy ( f1, f2, G_FILE_COPY_OVERWRITE, cancellable,
						xfer_update_copy_process, & copy, & error ) ;
		
			g_free ( m ) ;
		}
		else
			g_file_copy ( f1, f2, G_FILE_COPY_OVERWRITE, cancellable,
					xfer_update_copy_process, & copy, & error ) ;
		
		if ( error )
			g_critical ( "Cannot copy file: %s", error -> message ) ;
		
		g_object_unref ( f1 ) ;
		g_object_unref ( f2 ) ;
		
		g_free ( new_name ) ;
	}
	
	
	g_object_unref ( cancellable ) ;
	g_list_foreach ( list, g_free, null ) ;
	
	g_list_free ( list ) ;
	gtk_widget_destroy ( dialog ) ;
}


///| Double vision ?
void xfer_copy_list ( Explorer * e, GList * list, gchar * destination )
{
	if ( ! g_file_test ( destination, G_FILE_TEST_IS_DIR ))
	{
		g_warning ( "Cannot copy multiple files to something "
					"other than a directory. Yea" ) ;
		
		return ;
	}
	
	GtkDialog * dialog = gtk_dialog_new_with_buttons ( "Copying files ...",
							e -> window,
							GTK_DIALOG_MODAL,
							"Cancel",
							0,
							null ) ;
	
	GtkImage * image = gtk_image_new_from_stock ( "gtk-copy", GTK_ICON_SIZE_DIALOG ) ;
	gchar * markup = g_markup_printf_escaped ( 
						"<span size=\"large\"><b>"
						"Copying files ...\n\n"
						"</b></span>"
						"Please wait while files are being copied." ) ;
	
	GtkLabel * l = gtk_label_new ( null ) ;
	gtk_label_set_markup ( l, markup ) ;
	
	g_free ( markup ) ;
	
	GtkWidget * hbox = gtk_hbox_new ( no, 0 ) ;
	GtkWidget * vbox = gtk_hbox_new ( no, 0 ) ;
	
	gtk_box_pack_start ( hbox, image, no, no, 5 ) ;
	gtk_box_pack_start ( hbox, l, yes, yes, 2 ) ;
	
	gtk_box_pack_start ( vbox, hbox, yes, yes, 5 ) ;
	gtk_label_set_line_wrap ( l, on ) ;

	GtkProgressBar  * bar1 = gtk_progress_bar_new (),
					* bar2 = gtk_progress_bar_new () ;
	
	gtk_box_pack_start ( vbox, bar1, no, no, 2 ) ;
	gtk_box_pack_start ( vbox, bar2, no, no, 2 ) ;
	
	gtk_box_pack_start ( dialog -> vbox, vbox, yes, yes, 5 ) ;
	gtk_widget_show_all ( dialog ) ;
	
	gint i = 0, len = g_list_length ( list ) ;
	GCancellable * cancellable = g_cancellable_new () ;
	
	Copy copy ;
	
	copy.bar1 = bar1 ;
	copy.bar2 = bar2 ;
	
	copy.list = list ;
	copy.total_files = len ;
	
	copy.current_file = 0 ;
	copy.cancellable = cancellable ;
	
	gchar * source = explorer_get_current_folder ( e ) ;
	
	for ( i = 0 ; i < len ; i ++ )
	{
		GFile * f1 = g_file_new_for_path ( g_list_nth_data ( list, i )),
			  * f2 = null ;
		
		gchar * new_name = g_build_filename ( source, g_list_nth_data ( list, i ), null ) ;
		copy.current_file = i ;
		
		/* We might not need this
		if ( g_file_test ( g_list_nth_data ( list, i ), G_FILE_TEST_IS_DIR ))
			g_mkdir_with_parents ( new_name, 0777 ) ;
		*/
		
		f2 = g_file_new_for_path ( new_name ) ;
		GError * error = null ;
		
		if ( g_file_test ( new_name, G_FILE_TEST_EXISTS ) && ! g_file_test ( new_name, G_FILE_TEST_IS_DIR ))
		{
			gchar * m = g_strdup_printf ( "The file %s exists. Overwrite ?", new_name ) ;
			if ( prompt_question ( m ))
				g_file_copy ( f1, f2, G_FILE_COPY_OVERWRITE, cancellable,
						& copy, e, & error ) ;
		
			g_free ( m ) ;
		}
		else
			g_file_copy ( f1, f2, G_FILE_COPY_OVERWRITE, cancellable,
					& copy, e, & error ) ;
		
		if ( error )
			g_critical ( "Cannot copy file: %s", error -> message ) ;
		
		g_object_unref ( f1 ) ;
		g_object_unref ( f2 ) ;
		
		g_free ( new_name ) ;
	}
	
	
	g_object_unref ( cancellable ) ;
	g_list_foreach ( list, g_free, null ) ;
	
	g_list_free ( list ) ;
	gtk_widget_destroy ( dialog ) ;
	
	g_free ( source ) ;
}

void xfer_xfer ( Explorer * e, ClipboardAction action, GList * list, gchar * destination )
{
	if ( ! g_file_test ( destination, G_FILE_TEST_IS_DIR ))
	{
		g_warning ( "Cannot copy multiple files to something "
					"other than a directory. Yea" ) ;
		
		return ;
	}
	
	GtkDialog * dialog = null ;
	GtkImage * image = null ;
	
	gchar * markup = null ;
	
	if ( action == COPY )
	{
	
		dialog = gtk_dialog_new_with_buttons ( "Copying files ...",
								e -> window,
								GTK_DIALOG_MODAL,
								"Cancel",
								0,
								null ) ;
		
		image = gtk_image_new_from_stock ( "gtk-copy", GTK_ICON_SIZE_DIALOG ) ;
		markup = g_markup_printf_escaped ( 
							"<span size=\"large\"><b>"
							"Copying files ...\n\n"
							"</b></span>"
							"Please wait while files are being copied." ) ;
	}
	
	else
	{
	
		dialog = gtk_dialog_new_with_buttons ( "Moving files ...",
								e -> window,
								GTK_DIALOG_MODAL,
								"Cancel",
								0,
								null ) ;
		
		image = gtk_image_new_from_stock ( "gtk-cut", GTK_ICON_SIZE_DIALOG ) ;
		markup = g_markup_printf_escaped ( 
							"<span size=\"large\"><b>"
							"Moving files ...\n\n"
							"</b></span>"
							"Please wait while files are being moved." ) ;
	}

	GtkLabel * l = gtk_label_new ( null ) ;
	gtk_label_set_markup ( l, markup ) ;
	
	g_free ( markup ) ;
	
	GtkWidget * hbox = gtk_hbox_new ( no, 0 ) ;
	GtkWidget * vbox = gtk_hbox_new ( no, 0 ) ;
	
	gtk_box_pack_start ( hbox, image, no, no, 5 ) ;
	gtk_box_pack_start ( hbox, l, yes, yes, 2 ) ;
	
	gtk_box_pack_start ( vbox, hbox, yes, yes, 5 ) ;
	gtk_label_set_line_wrap ( l, on ) ;

	GtkProgressBar  * bar1 = gtk_progress_bar_new (),
					* bar2 = gtk_progress_bar_new () ;
	
	gtk_box_pack_start ( vbox, bar1, no, no, 2 ) ;
	gtk_box_pack_start ( vbox, bar2, no, no, 2 ) ;
	
	gtk_box_pack_start ( dialog -> vbox, vbox, yes, yes, 5 ) ;
	gtk_widget_show_all ( dialog ) ;
	
	gint i = 0, len = g_list_length ( list ) ;
	GCancellable * cancellable = g_cancellable_new () ;
	
	Copy copy ;
	
	copy.bar1 = bar1 ;
	copy.bar2 = bar2 ;
	
	copy.list = list ;
	copy.total_files = len ;
	
	copy.current_file = 0 ;
	copy.cancellable = cancellable ;
	
	gchar * source = explorer_get_current_folder ( e ) ;
	
	for ( i = 0 ; i < len ; i ++ )
	{
		gchar * path = g_list_nth_data ( list, i ) ;
		gchar * basename = g_path_get_basename ( path ) ;
		
		GFile * f1 = g_file_new_for_path ( path ),
			  * f2 = null ;
		
		gchar * new_name = g_build_filename ( source, basename, null ) ;
		copy.current_file = i ;
		
		f2 = g_file_new_for_path ( new_name ) ;
		GError * error = null ;
		
		if ( g_file_test ( new_name, G_FILE_TEST_EXISTS ) && ! g_file_test ( new_name, G_FILE_TEST_IS_DIR ))
		{
			gchar * m = g_strdup_printf ( "The file %s exists. Overwrite ?", new_name ) ;
			if ( prompt_question ( m ) == YES )
				g_file_copy ( f1, f2, G_FILE_COPY_OVERWRITE, cancellable,
						xfer_update_copy_process, & copy, & error ) ;
		
			g_free ( m ) ;
		}
		if ( g_file_test ( path, G_FILE_TEST_IS_DIR ))	
			g_mkdir_with_parents ( new_name, 0777 ) ;
		
		else
			g_file_copy ( f1, f2, G_FILE_COPY_OVERWRITE, cancellable,
					xfer_update_copy_process, & copy, & error ) ;
		
		if ( error )
			g_critical ( "Cannot copy file: %s", error -> message ) ;
		
		/* Be careful */
		else if ( action == CUT )
		{
			GError * error = null ;
			//if ( ! g_file_delete ( f1, null, & error ))
				//g_critical ( "Cannot delete source file %s: %s", g_list_nth_data ( list, i ), error -> message ) ;
			g_debug ( "File %s will be removed here.", g_list_nth_data ( list, i )) ;
		}
		
		g_object_unref ( f1 ) ;
		g_object_unref ( f2 ) ;
		
		g_free ( basename ) ;
		g_free ( new_name ) ;
	}
	
	
	g_object_unref ( cancellable ) ;
	
	gtk_widget_destroy ( dialog ) ;
	g_free ( source ) ; 
}
